import os
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt
import hashlib
import copy
import json
import threading
# from persistence.parse_file import ParseFile


def calculate_md5(input_file):
    '''计算django收到文件的MD5
    :param input_file
    :return 文件不存在返回空字符串,否则返回MD5
    '''
    if not input_file:
        return ''
    md5 = hashlib.md5()
    for chunk in input_file.chunks():
        md5.update(chunk)
    return md5.hexdigest()


def read_chunks(file_handle, chunk_size=8192):
    '''分块读取大文件'''
    while True:
        data = file_handle.read(chunk_size)
        if not data:
            break
        yield data


def md5_local_file(file_handle):
    '''本地文件计算MD5'''
    hasher = hashlib.md5()
    for chunk in read_chunks(file_handle):
        hasher.update(chunk)
    return hasher.hexdigest()


# class StartParseFile(threading.Thread):
#     def __init__(self, file_abs_path ):
#         threading.Thread.__init__(self)
#         self.file_abs_path = file_abs_path

#     def run(self):
#         ParseFile().parse(self.file_abs_path)


@csrf_exempt
def upload(request):
    """处理分片文件的接收与保存,判断分片的MD5是否与接受到的相同"""
    ret_msg = {
        'success':False,
        'md5':'',
        'msg':'',
    }
    if request.method == 'POST':
        my_file = request.FILES.get('file')
        if not my_file:
            ret_msg['msg'] = "文件不存在"
            return HttpResponse(json.dumps(ret_msg), content_type="application/json")

        ret_msg['md5'] = calculate_md5(copy.deepcopy(my_file))
        if ret_msg['md5'] not in request.POST.get('md5'):
            ret_msg['msg'] = "MD5校验失败"
            return HttpResponse(json.dumps(ret_msg), content_type="application/json")
        else:
            ret_msg['msg'] = "成功接收"
            ret_msg['success'] = True

        task = request.POST.get('task_id')          # 获取文件唯一标识符
        filename = request.POST.get('filename')          # 获取文件唯一标识符
        print(filename)
        chunk = request.POST.get('chunk', 0)        # 获取该分片在所有分片中的序号
        filename = '%s%s' % (task, chunk)           # 构成该分片唯一标识符，也是保存的文件名
        with open('files/' + filename, 'wb') as f:
            f.write(my_file.read())
        return HttpResponse(json.dumps(ret_msg), content_type="application/json")

    return JsonResponse(ret_msg)


@csrf_exempt
def upload_success(request):
    """小文件传输成功后，前端会自动发起请求到此函数，将小文件合并为大文件，并删除缓存的小文件"""
    ret_msg = {
        'success':True,
        'md5':'',
        'msg':'',
    }
    target_filename = request.GET.get('filename')
    task = request.GET.get('task_id')           # 获取文件的唯一标识符
    chunk = 0                                   # 分片序号
    with open('files/%s' % target_filename, 'wb') as target_file:   # 创建新文件，使用上传文件的文件名
        while True:
            try:
                filename = 'files/%s%d' % (task, chunk)
                source_file = open(filename, 'rb')                  # 按序打开每个分片
                target_file.write(source_file.read())               # 读取分片内容写入新文件
                source_file.close()
            except IOError:
                break
            chunk += 1
            os.remove(filename)                                     # 删除该分片，节约空间

    with open('files/%s' % target_filename,'rb') as f:
        ret_msg['md5'] = md5_local_file(f)
    if request.GET.get('md5') not in ret_msg['md5']:
        ret_msg['success'] = False
        ret_msg['msg'] = "文件合并MD5校验出错"
        return HttpResponse(json.dumps(ret_msg), content_type="application/json")
    project_abs_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    file_abs_path = os.path.join(project_abs_path,"files",target_filename)
    # file_parse_thread = StartParseFile(file_abs_path)
    # file_parse_thread.start()
    return HttpResponse(json.dumps(ret_msg), content_type="application/json")

def test(request):
    response = {}
    response['data'] = 2
    return JsonResponse(response)
